#include "lib.h"

/******************************************************************************
 *
 * Définition de la classe Sort
 *
 *****************************************************************************/

Sort::Sort(const unsigned int& ecole, const unsigned int& niveau,
	   const unsigned int& numero)
{
  this -> clear();

  this -> push_back(ecole);
  this -> push_back(niveau);
  this -> push_back(numero);
}

Sort::Sort(const Sort& sort)
{
  this -> clear();

  this -> push_back(sort[0]);
  this -> push_back(sort[1]);
  this -> push_back(sort[2]);
}

Sort::~Sort()
{}

bool Sort::operator<(const Sort& sort) const
{
  bool ok( verifie() && sort.verifie());

  if(!ok)
    {
      dout(DEBUG) << *this << " <  " << sort << " ?" << endl;
      dout(ERR) << "Problème dans Sort::operator<" << endl;
      exit(1);
    }

  return (((*this)[0] <= sort[0]) && ((*this)[1] <= sort[1]) && ((*this)[2] < sort[2]));
}

bool Sort::operator>(const Sort& sort) const
{
  bool ok(verifie() && sort.verifie());

  if(!ok)
    {
      dout(DEBUG) << *this << " >  " << sort << " ?" << endl;
      dout(ERR) << "Problème dans Sort::operator>" << endl;
      exit(1);
    }

  return (((*this)[0] >= sort[0]) && ((*this)[1] >= sort[1]) && ((*this)[2] > sort[2]));
}

bool Sort::operator==(const Sort& sort) const
{
  bool ok(verifie() && sort.verifie());

  if(!ok)
    {
      dout(DEBUG) << *this << " ==  " << sort << " ?" << endl;
      dout(ERR) << "Problème dans Sort::operator>" << endl;
      exit(1);
    }

  return (((*this)[0] == sort[0]) && ((*this)[1] == sort[1]) && ((*this)[2] == sort[2]));
}

bool Sort::verifie() const
{
  return (size() == 3);
}

ostream& operator<<(ostream& out, const Sort& sort)
{
  return out << sort[0] << ' ' << sort[1] << ' ' << sort[2] << ' ';
}

/******************************************************************************
 *
 * Définition des fonctions
 *
 *****************************************************************************/

int puissance(int a, unsigned int b)
{
  if (b > 0)
    return a * puissance (a, b-1);
  else
    return 1;      
}

unsigned int digit(const int& a, const int& b)
{
  unsigned int retour(0);
  retour = a / puissance(10, b);
  if (retour > 9)
	  retour = retour % 10;
  return retour;
}

string write_int(const unsigned int& nbr)
{
  string retour("");
  unsigned int tmp;
  for (unsigned int i(7); i != 0; i--)
    {
      tmp = digit(nbr, i-1);
      switch (tmp)
	{
	case 1:
	  retour += '1';
	  break;
	case 2:
	  retour += '2';
	  break;
	case 3:
	  retour += '3';
	  break;
	case 4:
	  retour += '4';
	  break;
	case 5:
	  retour += '5';
	  break;
	case 6:
	  retour += '6';
	  break;
	case 7:
	  retour += '7';
	  break;
	case 8:
	  retour += '8';
	  break;
	case 9:
	  retour += '9';
	  break;
	case 0:
	  if (retour.size() != 0)
	    retour += '0';
	  break;
	}
    }

  if (retour == "")
    return "0";
  else
    return retour;
}

unsigned int demander_unsigned(const string& question)
{
  bool encore(false);
  unsigned int retour;
  string poubelle;

  do
    {
      dout(BLANK) << question;
      cin >> retour;

      encore = cin.fail();

      if (encore)
	{
	  dout(WARN) << "Entrer un nombre entier!" << endl;
	  cin.clear();
	  getline(cin, poubelle);
	}
    }
  while(encore);

  return retour;
}

unsigned int demander_unsigned_borne(const string& question,
				     const unsigned int& min,
				     const unsigned int& max)
{
  unsigned int nbr;
  bool encore(false);

  do
    {
      nbr = demander_unsigned(question);

      encore = (nbr < min || nbr > max);

      if (encore)
	dout(WARN) << "Entrer un nombre entier entre " << min
		   << " et " << max << " !" << endl;
    }
  while(encore);

  return nbr;
}

string affiche_accent(const string& brut)
{
  string retour(brut);
  unsigned int loc(retour.find("\\'", 0));
  while (loc != string::npos)
    {
      dout(LFUNC) << retour << ' ' << loc << endl;
      retour.replace(loc, 3, "é");
      loc = retour.find("\\'", 0);
    }
  loc = retour.find("\\`", 0);
  while (loc != string::npos)
    {
      dout(LFUNC) << retour << ' ' << loc << endl;
      retour.replace(loc, 3, "à");
      loc = retour.find("\\`", 0);
    }
  loc = retour.find("\\^", 0);
  while (loc != string::npos)
    {
      dout(LFUNC) << retour << ' ' << loc << endl;
      retour.replace(loc, 3, "ô");
      loc = retour.find("\\^", 0);
    }
  return retour;
}

unsigned int affiche_sorts(const unsigned int& ecole,
			   const unsigned int& niveau)
{
  const Sorts_ecoles *ptr;
  unsigned int taille, i;
  bool ok(true);

  switch(ecole)
    {
    case 0:
      ptr = &Abjuration[0];
      taille = 4;
      break;
    case 1:
      ptr = &Alteration[0];
      taille = 20;
      break;
    case 2:
      ptr = &Conjuration[0];
      taille = 6;
      break;
    case 3:
      ptr = &Divination[0];
      taille = 5;
      break;
    case 4:
      ptr = &Enchantement[0];
      taille = 6;
      break;
    case 5:
      ptr = &Illusion[0];
      taille = 6;
      break;
    case 6:
      ptr = &Invocation[0];
      taille = 8;
      break;
    case 7:
      ptr = &Necromancie[0];
      taille = 4;
      break;
    case 8:
      ptr = &Alchimie[0];
      taille = 6;
      break;
    case 9:
      ptr = &Artifices[0];
      taille = 3;
      break;
    case 10:
      ptr = &Dimension[0];
      taille = 3;
      break;
    case 11:
      ptr = &ElementAir[0];
      taille = 3;
      break;
    case 12:
      ptr = &ElementEau[0];
      taille = 1;
      break;
    case 13:
      ptr = &ElementFeu[0];
      taille = 4;
      break;
    case 14:
      ptr = &ElementTerre[0];
      taille = 1;
      break;
    case 15:
      ptr = &Eurythmique[0];
      taille = 6;
      break;
    case 16:
      ptr = &Forces[0];
      taille = 4;
      break;
    case 17:
      ptr = &Geometrie[0];
      taille = 4;
      break;
    case 18:
      ptr = &Mentalisme[0];
      taille = 3;
      break;
    case 19:
      ptr = &Ombres[0];
      taille = 3;
      break;
    default:
      dout(WARN) << "Erreur dans l'école de magie" << endl;
      ok = false;
    }

  if (ok)
    {
      for (i = 0; i < taille; i++, ptr++)
	{
	  if (ptr -> niveau != niveau)
	    continue;
	  dout(BLANK) << setw(2) << ptr -> numero + 1 << ' '
		      << ptr -> Nom_sort << endl;
	}

      return taille;
    }
  return 0;
}

bool safe_push_back(vector<unsigned int> *ptr, const unsigned int& valeur)
{
  vector<unsigned int>::iterator loc, Begin(ptr -> begin()), End(ptr -> end());
  loc = find(Begin, End, valeur);

  dout(DEBUG) << "Position : " << (int) (loc - Begin)
	      << " sur une taille de " << ptr -> size() << endl;

  return !(loc == End);
}

void gerer_espaces_blancs(char* tab[], int& nbr,
			  vector<string>& retour)
{
  retour.clear();
  for (unsigned int i(0); i < nbr; i++)
    {
      retour.push_back(tab[i]);
      dout(DEBUG) << retour.back() << endl;
    }

  dout(DEBUG) << endl;

  vector<string>::iterator it, Begin(++retour.begin()), End(retour.end());

  for (it = ++Begin; it != retour.end(); it++)
    {
      if ((*it)[0] < 48 || (*it)[0] > 57)
	{
	  *(it - 1) += "\\ " + *it;
	  retour.erase(it);
	  dout(DEBUG) << "Fusion en " << *(it -1) << endl;
	  it--;
	}
    }

  dout(DEBUG) << endl;

  unsigned int loc(retour[1].find("\'"));
  if (loc != -1)
    retour[1].replace(loc, 1, "\\'");

  nbr = retour.size();
}
